﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using OpenCvSharp;
using FinallyVideoCaptureTest.Assist;
using System.Threading;

namespace FinallyVideoCaptureTest
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
        enum DisplayType
        {
            CaptureCard = 0,
            SimpleVideo = 1
        }
        private string dbPath = "TestFrames.db4o";
        private string filePath = "";
        private bool isFirstFrame = true;
        private System.Windows.Forms.Timer time;
        private DisplayType CurrentDisplayModel;
        private CvRect rect;
        private CvSize size;
        private int frameRate = 0;
        private bool isSureParams = false;
        private long _incomingPeopleCount;
        private long _outgoingPeopleCount;

        private void btnSave_Click(object sender, EventArgs e)
        {
            int x = -1;
            int y = -1;
            int width = -1;
            int height = -1;
            int sWidth = -1;
            int sHeight = -1;
            int fRate = -1;
            try
            {
                x = Convert.ToInt32(txtX.Text.Trim());
                y = Convert.ToInt32(txtY.Text.Trim());
                width = Convert.ToInt32(txtWidth.Text.Trim());
                height = Convert.ToInt32(txtHeight.Text.Trim());
                sWidth = Convert.ToInt32(txtSWidth.Text.Trim());
                sHeight = Convert.ToInt32(txtSHeight.Text.Trim());
                fRate = Convert.ToInt32(txtSFrameRate.Text.Trim());
            }
            catch (System.Exception ex)
            {
                MessageBox.Show("输入的参数不合法！", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            rect.X = x;
            rect.Y = y;
            rect.Width = width;
            rect.Height = height;
            size.Width = sWidth;
            size.Height = sHeight;
            frameRate = fRate;
            isSureParams = true;
            Properties.Settings settings = Properties.Settings.Default;
            settings.FrameRate = fRate.ToString();
            settings.PeopleSize = string.Format("{0},{1}", sWidth, sHeight);
            settings.MonitorArea = string.Format("{0},{1},{2},{3}", x, y, width, height);
            settings.Save();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            this._threadBase = new ThreadBase();
            Stopped += new EventHandler(MainForm_Stopped);
            InitParams();
            InitTimer();
        }

        //初始化参数
        private void InitParams()
        {
            Properties.Settings setting = Properties.Settings.Default;
            string[] rectArray = setting.MonitorArea.Split(',');
            string[] sizeArray = setting.PeopleSize.Split(',');
            rect = new CvRect(Convert.ToInt32(rectArray[0]),
                Convert.ToInt32(rectArray[1]),
                Convert.ToInt32(rectArray[2]),
                Convert.ToInt32(rectArray[3]));
            size = new CvSize(Convert.ToInt32(sizeArray[0]), Convert.ToInt32(sizeArray[1]));
            frameRate = Convert.ToInt32(setting.FrameRate);
            SetControlValue();
        }

        //初始化参数  设置控件按钮
        private void SetControlValue()
        {
            txtX.Text = rect.X.ToString();
            txtY.Text = rect.Y.ToString();
            txtWidth.Text = rect.Width.ToString();
            txtHeight.Text = rect.Height.ToString();
            txtSWidth.Text = size.Width.ToString();
            txtSHeight.Text = size.Height.ToString();
            txtSFrameRate.Text = frameRate.ToString();
        }

        private void InitTimer()
        {
            time = new System.Windows.Forms.Timer();
            time.Tick += new EventHandler(time_Tick);
            time.Interval = 1000;
        }

        void time_Tick(object sender, EventArgs e)
        {
            txtCurTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
        }

        private void chSettingMonitorArea_Click(object sender, EventArgs e)
        {
            chSettingMonitorArea.Checked = chSettingMonitorArea.Checked ? true : false;
        }

        private void chSettingMonitorArea_CheckedChanged(object sender, EventArgs e)
        {
            if (chSettingMonitorArea.Checked)
            {
                SettingsForm settingsForm = new SettingsForm();
                if (settingsForm.ShowDialog() == DialogResult.OK)
                {
                    filePath = settingsForm.FilePath;
                    if (settingsForm.GetUpdateState)
                    {
                        rect = settingsForm.GetMonitorArea;
                        size.Height = rect.Height;
                        SetControlValue();
                    }
                }
            }
        }

        private void txtLength_TextChanged(object sender, EventArgs e)
        {
            txtSHeight.Text = txtHeight.Text;
        }


        private Thread threadOfCaptureCard = null;
        private Thread threadOfVideo = null;

        //连接 视频采集卡 控件
        private void tsbConnect_Click(object sender, EventArgs e)
        {
            bool state = false;
            if (!isSureParams)
            {
                MessageBox.Show("请确认参数！");
                return;
            }
            if (this.CurrentDisplayModel == DisplayType.CaptureCard)
            {
                short res = axSDK_20001.Connect(false);
                if (res >= 0)
                {
                    axSDK_20001.SetPreviewWHT(720, 576, 1);
                    threadOfCaptureCard = new Thread(new ThreadStart(AnalysePicOnCaptureCard));
                    threadOfCaptureCard.SetApartmentState(ApartmentState.STA);
                    threadOfCaptureCard.IsBackground = true;
                    threadOfCaptureCard.Start();
                    state = true;
                }
                else
                {
                    MessageBox.Show("无设备可以连接！");
                }
            }
            else if (this.CurrentDisplayModel == DisplayType.SimpleVideo)
            {
                if (string.IsNullOrEmpty(filePath) || !filePath.EndsWith(".avi"))
                {
                    MessageBox.Show("请选择视频文件！");
                    return;
                }
                threadOfVideo = new Thread(new ThreadStart(AnalysePicOnVideo));
                threadOfVideo.IsBackground = true;
                threadOfVideo.Start();
                state = true;
            }
            if (state)
            {
                txtStartTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                SetControlState(true);
            }
        }

        private void SetControlState(bool res)
        {
            this.isFirstFrame = true;
            this.isStopThread = res;
            this.isSureParams = res;
            this.tsbConnect.Enabled = !res;
            if (res)
            {
                if (this.CurrentDisplayModel == DisplayType.CaptureCard)
                    lblConnState.Text = "已连接";
                else if (this.CurrentDisplayModel == DisplayType.SimpleVideo)
                    lblConnState.Text = "播放";
                lblConnState.ForeColor = Color.Green;
                time.Start();
            }
            else
            {
                if (this.CurrentDisplayModel == DisplayType.CaptureCard)
                    lblConnState.Text = "断开";
                else if (this.CurrentDisplayModel == DisplayType.SimpleVideo)
                    lblConnState.Text = "停止";
                lblConnState.ForeColor = Color.Red;
                time.Stop();
            }
            time.Enabled = res;
        }


        //终止分析视频线程  
        void MainForm_Stopped(object sender, EventArgs e)
        {
            if (this.CurrentDisplayModel == DisplayType.SimpleVideo)
            {
                pictureBox1.Image = null;
            }
            SetControlState(false);

        }

        private void tsbDisconnect_Click(object sender, EventArgs e)
        {
            RequestStop();

            if (this.CurrentDisplayModel == DisplayType.CaptureCard)
            {
                axSDK_20001.Disconnect();
            }
        }
        //委托终止分析线程
        public void RequestStop()
        {
            this.isStopThread = false;
        }

        private void tsbStatistics_Click(object sender, EventArgs e)
        {
            StatisticsForm statisticsForm = new StatisticsForm();
            statisticsForm.ShowDialog();
        }

        private void tabMonitorMode_Selected(object sender, TabControlEventArgs e)
        {
            this.CurrentDisplayModel = (DisplayType)Enum.Parse(typeof(DisplayType), e.TabPage.Tag.ToString());

            if (this.CurrentDisplayModel == DisplayType.CaptureCard)
            {
                chSettingMonitorArea.Text = "根据已有文件设置监控区域";
                tsbConnect.Text = "连接";
                tsbDisconnect.Text = "断开";
                lblMonitorState.Text = "连接状态:";
            }
            else if (this.CurrentDisplayModel == DisplayType.SimpleVideo)
            {
                chSettingMonitorArea.Text = "选择视频文件";
                tsbConnect.Text = "播放";
                tsbDisconnect.Text = "停止";
                lblMonitorState.Text = "播放状态:";
            }
        }


        public event EventHandler Stopped;
        private ThreadBase _threadBase;
        private bool isStopThread = false;


        //分析视频  
        private unsafe void AnalysePicOnVideo()
        {
            PeopleCountModel countModel = new PeopleCountModel();
            OpenCvSharp.CvCapture capture = new OpenCvSharp.CvCapture(filePath);
            IplImage pFrame = null;
            IntPtr model = IntPtr.Zero;
            while ((pFrame = capture.QueryFrame()) != null && isStopThread == true)
            {
                pFrame.IsEnabledDispose = false;
                if (isFirstFrame)
                {
                    model = AccessBaseTarget.InitPeoModel(pFrame.CvPtr, rect, size, frameRate);
                    countModel = *(PeopleCountModel*)model.ToPointer();
                    isFirstFrame = false;
                }
                Bitmap bmp = pFrame.ToBitmap();
                AccessBaseTarget.UpdatePeoModel(ref countModel, pFrame.CvPtr);
                Frame frame = new Frame();
                if (countModel.iInNum > 0 || countModel.iOutNum > 0)
                {
                    Db4oProvider provider = new Db4oProvider(dbPath);
                    frame.CaptureTime = DateTime.Now;
                    frame.PicSavePath = GeneratorPicRefInfo.GeneratorFileSavePath(GeneratorPicRefInfo.GeneratorFileName(frame.CaptureTime));
                    frame.PersonInCount = countModel.iInNum;
                    frame.PersonOutCount = countModel.iOutNum;
                    pFrame.SaveImage(frame.PicSavePath);
                    provider.StartServer();
                    provider.SaveFrame(frame);
                    provider.StopServer();
                }
                ShowInfoOnVideo(frame, bmp);
            }
            pFrame = null;

            if (model != IntPtr.Zero)
                AccessBaseTarget.ReleasePeoModel(model);
            this._threadBase.Post(OnStopped, EventArgs.Empty);
        }

        protected virtual void OnStopped(EventArgs e)
        {
            if (this.Stopped != null)
            {
                this.Stopped(this, e);
            }
        }

        private void ShowInfoOnVideo(Frame frame, Bitmap bmp)
        {
            if (this.InvokeRequired)
            {
                Action<Frame, Bitmap> ac = this.ShowInfoOnVideo;
                this.BeginInvoke(ac, frame, bmp);
                return;
            }
            int inPeo = -1;
            int ouPeo = -1;
            if (lblInCount.Text == "" || lblOutCount.Text == "")
            {
                inPeo = 0;
                ouPeo = 0;
            }
            else
            {
                inPeo = Convert.ToInt32(lblInCount.Text) + frame.PersonInCount;
                ouPeo = Convert.ToInt32(lblOutCount.Text) + frame.PersonOutCount;
            }
            pictureBox1.Image = bmp;
            lblInCount.Text = inPeo.ToString();
            lblOutCount.Text = ouPeo.ToString();
        }

        //分析视频采集卡的抽帧图片
        private unsafe void AnalysePicOnCaptureCard()
        {
            PeopleCountModel countModel = new PeopleCountModel();
            IntPtr model = IntPtr.Zero;
            string tempPicPath = "temp.jpg";
            int count = 0;
            bool initialized = false;
            while (this.isStopThread)
            {
                count++;
                var saveSucceed = axSDK_20001.EditCopy();

                if (count % Properties.Settings.Default.FrameSkip == 0)
                {
                    if (!saveSucceed) continue;
                    if (!Clipboard.ContainsImage()) continue;

                    IplImage pFrame = null;
                    try
                    {
                        var bmp = Clipboard.GetImage();
                        var mem = new System.IO.MemoryStream();
                        bmp.Save(mem, ImageFormat.Jpeg);
                        bmp = Image.FromStream(mem);
                        pFrame = IplImage.FromBitmap((Bitmap)bmp);
                    }
                    catch { continue; }

                    if (pFrame.CvPtr == IntPtr.Zero) continue;

                    if (!initialized)
                    {
                        model = AccessBaseTarget.InitPeoModel(pFrame.CvPtr, rect, size, frameRate);
                        countModel = *(PeopleCountModel*)model.ToPointer();
                        initialized = true;
                    }
                    else
                    {
                        AccessBaseTarget.UpdatePeoModel(ref countModel, pFrame.CvPtr);

                        if (countModel.iInNum > 0 || countModel.iOutNum > 0)
                        {
                            Frame frame = new Frame();
                            frame.CaptureTime = DateTime.Now;
                            frame.PersonInCount = countModel.iInNum;
                            frame.PersonOutCount = countModel.iOutNum;

                            ShowInfo(frame);

                            Db4oProvider provider = new Db4oProvider(dbPath);
                            provider.StartServer();
                            provider.SaveFrame(frame);
                            provider.StopServer();
                        }
                    }
                }
               
                Thread.Sleep(30);
            }

        }

        //显示人数信息
        private void ShowInfo(Frame frame)
        {
            if (this.InvokeRequired)
            {
                Action<Frame> ac = this.ShowInfo;
                this.BeginInvoke(ac, frame);
                return;
            }

            _incomingPeopleCount += frame.PersonInCount;
            _outgoingPeopleCount += frame.PersonOutCount;

            txtCurTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            lblInCount.Text = _incomingPeopleCount.ToString();
            lblOutCount.Text = _outgoingPeopleCount.ToString();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            RequestStop();
            if (this.CurrentDisplayModel == DisplayType.CaptureCard)
            {
                axSDK_20001.Disconnect();
            }
        }
    }

}
